// --------------------------------------------------------------------------------------------------------------------
// <copyright file="HighlightingSettingsManager.cs" company="Roman '4ux-nbIx' Novitsky">
//   Copyright (c) Roman '4ux-nbIx' Novitsky 2009
// </copyright>
// <summary>
//   Defines the HighlightingSettingsManager type.
// </summary>
// --------------------------------------------------------------------------------------------------------------------


namespace SettingsManager.ComponentSettingsManagers
{
  #region Namespace Imports

  using System;
  using System.Collections.Generic;
  using System.Globalization;
  using System.Xml;

  using JetBrains.Annotations;
  using JetBrains.ComponentModel;
  using JetBrains.ProjectModel;
  using JetBrains.ReSharper.Daemon;
  using JetBrains.ReSharper.Daemon.Impl;
  using JetBrains.Util;

  #endregion


  /// <summary>
  /// Describes and manipulates the highlighting component settings manager.
  /// </summary>
  internal sealed class HighlightingSettingsManager : ResharperComponentSettingsManager
  {
    #region Constructors and Destructors

    /// <summary>
    /// Initializes a new instance of the <see cref="HighlightingSettingsManager"/> class.
    /// </summary>
    public HighlightingSettingsManager()
      : base("HighlightingSettings", "Highlighting Settings")
    {
    }

    #endregion


    #region Public Methods

    /// <summary>
    /// Loads the settings.
    /// </summary>
    /// <param name="component">The component.</param>
    /// <param name="element">The element.</param>
    /// <param name="options">The options.</param>
    public override void LoadSettings(IXmlExternalizableComponent component, XmlElement element, object options)
    {
      HighlightingSettings highlightingSettings;
      var settingsManagerImpl =
        JetBrains.ReSharper.Daemon.HighlightingSettingsManager.Instance as HighlightingSettingsManagerImpl;

      if (settingsManagerImpl != null)
      {
        highlightingSettings = settingsManagerImpl.Settings.Clone();
        var settings = new HighlightingSettings(settingsManagerImpl);
        settings.ReadFromXml(element);
        settingsManagerImpl.Settings = settings;

        if (highlightingSettings != null)
        {
          settingsManagerImpl.Settings.IdentifierHighlightingEnabled = highlightingSettings.IdentifierHighlightingEnabled;
          settingsManagerImpl.Settings.AnalysisEnabled = highlightingSettings.AnalysisEnabled;
          settingsManagerImpl.Settings.ShowAnalysisOptionsInActionList = highlightingSettings.ShowAnalysisOptionsInActionList;
          settingsManagerImpl.Settings.ShowImportPopup = highlightingSettings.ShowImportPopup;
        }

        var settingsManagerOptions = options as HighlightingSettingsManagerOptions;

        if (settingsManagerOptions == null)
        {
          return;
        }

        if (settingsManagerOptions.ForceEnableCodeAnalysis)
        {
          settingsManagerImpl.Settings.AnalysisEnabled = true;
        }

        SolutionManager solutionManager = SolutionManager.Instance;

        if (solutionManager == null || solutionManager.CurrentSolution == null)
        {
          return;
        }

        SolutionAnalysisService analysisService = SolutionAnalysisService.GetInstance(solutionManager.CurrentSolution);

        if (analysisService != null && settingsManagerOptions.ForceEnableSolutionWideAnalysis)
        {
          analysisService.AnalysisEnabledOption = true;
        }
      }
      else
      {
        base.LoadSettings(component, element, options);
      }
    }


    /// <summary>
    /// Saves the settings.
    /// </summary>
    /// <param name="component">The component.</param>
    /// <param name="element">The element.</param>
    /// <param name="options">The options.</param>
    public override void SaveSettings(IXmlExternalizableComponent component, XmlElement element, [CanBeNull] object options)
    {
      var settingsManagerImpl = component as HighlightingSettingsManagerImpl;

      if (settingsManagerImpl == null)
      {
        return;
      }

      var dictionary = new Dictionary<string, string>();

      foreach (JetBrains.ReSharper.Daemon.HighlightingSettingsManager.ConfigurableSeverityItem item in
        settingsManagerImpl.SeverityConfigurations)
      {
        dictionary.Add(item.Id, item.DefaultSeverity.ToString());
      }

      HighlightingSettings highlightingSettings = settingsManagerImpl.Settings;

      foreach (string id in highlightingSettings.SeverityIds)
      {
        if (dictionary.ContainsKey(id))
        {
          dictionary[id] = highlightingSettings.GetSeverity(id).ToString();
        }
      }

      XmlDocument document = element.OwnerDocument;
      if (document == null)
      {
        return;
      }

      XmlElement valueAnalysisModeElement = document.CreateElement("ValueAnalysisMode");
      valueAnalysisModeElement.InnerText = highlightingSettings.ValueAnalysisMode.ToString();
      element.AppendChild(valueAnalysisModeElement);

      XmlElement severitySettingsElement = document.CreateElement("SeverityTable");

      foreach (KeyValuePair<string, string> keyValuePair in dictionary)
      {
        XmlElement severityElement = document.CreateElement(keyValuePair.Key);
        severityElement.InnerText = keyValuePair.Value;

        severitySettingsElement.AppendChild(severityElement);
      }

      element.AppendChild(severitySettingsElement);
    }


    /// <summary>
    /// Gets the options form.
    /// </summary>
    /// <returns>
    /// The options form.
    /// </returns>
    public override SettingsManagerOptionsForm GetOptionsForm()
    {
      return new HighlightingSettingsManagerOptionsForm();
    }


    /// <summary>
    /// Loads the options.
    /// </summary>
    /// <param name="optionsElement">
    /// The options element.
    /// </param>
    /// <returns>
    /// Returns an instance of <see cref="System.Object"/>.
    /// </returns>
    /// <exception cref="NotSupportedException">
    /// <c>NotSupportedException</c>.
    /// </exception>
    public override object LoadOptions(XmlElement optionsElement)
    {
      bool? forceEnableCodeAnalysis = null;
      bool? forceEnableSolutionWideAnalysis = null;

      XmlElement xmlElement = optionsElement["ForceEnableCodeAnalysis"];

      if (xmlElement != null)
      {
        bool result;

        if (bool.TryParse(xmlElement.InnerText, out result))
        {
          forceEnableCodeAnalysis = result;
        }
      }

      xmlElement = optionsElement["ForceEnableSolutionWideAnalysis"];

      if (xmlElement != null)
      {
        bool result;

        if (bool.TryParse(xmlElement.InnerText, out result))
        {
          forceEnableSolutionWideAnalysis = result;
        }
      }

      if (forceEnableCodeAnalysis.HasValue)
      {
        var options = new HighlightingSettingsManagerOptions { ForceEnableCodeAnalysis = forceEnableCodeAnalysis.Value };

        if (forceEnableSolutionWideAnalysis.HasValue)
        {
          options.ForceEnableSolutionWideAnalysis = forceEnableSolutionWideAnalysis.Value;
        }

        return options;
      }

      return null;
    }


    /// <summary>
    /// Saves the options.
    /// </summary>
    /// <param name="optionsElement">
    /// The options element.
    /// </param>
    /// <param name="options">
    /// The options.
    /// </param>
    /// <exception cref="NotSupportedException">
    /// <c>NotSupportedException</c>.
    /// </exception>
    public override void SaveOptions(XmlElement optionsElement, object options)
    {
      var settingsManagerOptions = (HighlightingSettingsManagerOptions)options;

      optionsElement.CreateLeafElementWithValue(
        "ForceEnableCodeAnalysis", settingsManagerOptions.ForceEnableCodeAnalysis.ToString(CultureInfo.InvariantCulture));

      optionsElement.CreateLeafElementWithValue(
        "ForceEnableSolutionWideAnalysis", settingsManagerOptions.ForceEnableSolutionWideAnalysis.ToString(CultureInfo.InvariantCulture));
    }

    #endregion
  }
}